package cn.xinfei.xdecision.common.service.component.scorecard.impl;

import cn.hutool.core.date.DateUtil;
import cn.xinfei.xdecision.common.dao.component.scorecard.ScorecardVersionMapper;
import cn.xinfei.xdecision.common.model.common.PageResult;
import cn.xinfei.xdecision.common.model.common.ResponseEntityDto;
import cn.xinfei.xdecision.common.model.common.requestParam.AssemblyRuleCodeReq;
import cn.xinfei.xdecision.common.model.common.requestParam.StatusParam;
import cn.xinfei.xdecision.common.model.component.scorecard.*;
import cn.xinfei.xdecision.common.model.component.scorecard.vo.ScorecardDetailVo;
import cn.xinfei.xdecision.common.model.component.scorecard.vo.ScorecardDimensionVo;
import cn.xinfei.xdecision.common.model.component.scorecard.vo.ScorecardVersionListVo;
import cn.xinfei.xdecision.common.model.component.scorecard.vo.ScorecardVersionVo;
import cn.xinfei.xdecision.common.model.component.strategyout.StrategyOutput;
import cn.xinfei.xdecision.common.model.datax.datamanage.Field;
import cn.xinfei.xdecision.common.model.login.SessionManager;
import cn.xinfei.xdecision.common.service.common.sso.SSOService;
import cn.xinfei.xdecision.common.service.common.sso.dto.SSOUserInfoReqDto;
import cn.xinfei.xdecision.common.service.common.sso.dto.SSOUserInfoRespDto;
import cn.xinfei.xdecision.common.service.component.ComponentCommonContext;
import cn.xinfei.xdecision.common.service.component.scorecard.ScorecardDetailConditionService;
import cn.xinfei.xdecision.common.service.component.scorecard.ScorecardDetailService;
import cn.xinfei.xdecision.common.service.component.scorecard.ScorecardDimensionService;
import cn.xinfei.xdecision.common.service.component.scorecard.ScorecardVersionService;
import cn.xinfei.xdecision.common.service.component.strategyout.StrategyOutputService;
import cn.xinfei.xdecision.common.service.datax.datamanage.FieldService;
import cn.xinfei.xdecision.common.utils.constant.CommonConst;
import cn.xinfei.xdecision.common.utils.constant.SysConstant;
import cn.xinfei.xdecision.common.utils.constant.enginex.EngineOperator;
import cn.xinfei.xdecision.common.utils.enums.enginex.ComponentStatusEnum;
import cn.xinfei.xdecision.common.utils.enums.enginex.ComponentTypeEnum;
import cn.xinfei.xdecision.common.utils.enums.enginex.ComponentVersionStatusEnum;
import cn.xinfei.xdecision.common.utils.exception.ApiException;
import cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum;
import cn.xinfei.xdecision.common.utils.util.BeanUtilsPlus;
import cn.xinfei.xdecision.common.utils.util.strategyx.CustomValueUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ScorecardVersionServiceImpl extends ServiceImpl<ScorecardVersionMapper, ScorecardVersion> implements ScorecardVersionService {

    @Autowired
    private ScorecardVersionMapper versionMapper;

    @Autowired
    private ScorecardDimensionService scorecardDimensionService;  // 维度

    @Autowired
    private ScorecardDetailService scorecardDetailService;  // 明细

    @Autowired
    private ScorecardDetailConditionService scorecardDetailConditionService;  // Condition

    @Autowired
    private FieldService fieldService;  // 指标(字段)

    @Resource
    private ScorecardVersionServiceImpl scorecardVersionService;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private ScorecardServiceImpl scorecardService;

    @Resource
    private SSOService ssoService;

    @Resource
    private StrategyOutputService outputService;

    @Override
    public ScorecardVersionVo queryById(Long id) {
        ScorecardVersion scorecardVersion = versionMapper.selectById(id);

        ScorecardVersionVo result = new ScorecardVersionVo();
        BeanUtils.copyProperties(scorecardVersion, result);
        result.setVersionNoDesc("V" + result.getVersionNo());
        result.setStatusDesc(Objects.requireNonNull(
                ComponentVersionStatusEnum.get(result.getStatus())).getName());

        List<ScorecardDimensionVo> scorecardDimensionVos = new ArrayList<>();
        List<ScorecardDimension> dimensionList = scorecardDimensionService.getDimensionListByVersionId(scorecardVersion.getId());
        if (dimensionList != null && !dimensionList.isEmpty()) {
            for (ScorecardDimension scorecardDimension : dimensionList) {
                scorecardDimensionVos.add(assemblyScorecardDimensionVo(scorecardDimension));
            }
        }
        result.setScorecardDimension(scorecardDimensionVos);
        //输出字段
        List<StrategyOutput> strategyOutputs = outputService.queryByTactics(new StrategyOutput(id, ComponentTypeEnum.SCORECARD.getType()));
        result.setStrategyOutputList(strategyOutputs);
        return result;
    }

    @Override
    public List<ScorecardVersionVo> queryVersionByScorecardCodes(List<String> scorecardCode, Integer status) {
        if (CollectionUtils.isEmpty(scorecardCode)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ScorecardVersion> lbd = new LambdaQueryWrapper<ScorecardVersion>()
                .in(ScorecardVersion::getScorecardCode, scorecardCode);
        if (Objects.nonNull(status)) {
            lbd.eq(ScorecardVersion::getStatus, status);
        }
        List<ScorecardVersion> versions = this.list(lbd);
        if (CollectionUtils.isEmpty(versions)) {
            return new ArrayList<>();
        }
        //校验版本状态，新建最多只会存在一个
        Map<String, Long> collect = versions.stream()
                .filter(x -> Objects.equals(x.getStatus(), ComponentVersionStatusEnum.NEW.getStatus()))
                .collect(Collectors.groupingBy(x -> x.getScorecardCode() + "_" + x.getStatus(), Collectors.counting()));
        StringBuilder stringBuilder = new StringBuilder();
        collect.forEach((key, value) -> {
            if (value > 1) {
                stringBuilder.append(key, 0, key.lastIndexOf("_")).append(";");
            }
        });
        if (stringBuilder.length() > 0) {
            throw new ApiException(
                    ErrorCodeEnum.ERROR_DECISION_VERSION.getCode()
                    , ErrorCodeEnum.ERROR_DECISION_VERSION.getMessage() + "评分卡编号：" + stringBuilder);
        }
        return BeanUtilsPlus.copyElements(versions, ScorecardVersionVo::new);
    }

    @Override
    public List<ScorecardVersionVo> queryVersionListByScorecardId(String scorecardCode, Long versionNo) {
        LambdaQueryWrapper<ScorecardVersion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ScorecardVersion::getScorecardCode, scorecardCode);
        queryWrapper.eq(ScorecardVersion::getVersionNo, versionNo);
        queryWrapper.orderByDesc(ScorecardVersion::getUpdatedTime);
        List<ScorecardVersion> scorecardVersions = versionMapper.selectList(queryWrapper);
        List<ScorecardVersionVo> scorecardVersionVoList = new ArrayList<>();
        for (ScorecardVersion scorecardVersion : scorecardVersions) {
            ScorecardVersionVo versionVo = new ScorecardVersionVo();
            BeanUtils.copyProperties(scorecardVersion, versionVo);
            scorecardVersionVoList.add(versionVo);
        }
        return scorecardVersionVoList;
    }

    @Override
    public List<ScorecardVersionVo> queryVersionListByScorecardId(String scorecardCode) {
        LambdaQueryWrapper<ScorecardVersion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ScorecardVersion::getScorecardCode, scorecardCode);
        queryWrapper.eq(ScorecardVersion::getStatus, 1);
        queryWrapper.orderByDesc(ScorecardVersion::getUpdatedTime);
        List<ScorecardVersion> scorecardVersions = versionMapper.selectList(queryWrapper);
        List<ScorecardVersionVo> scorecardVersionVoList = new ArrayList<>();
        for (ScorecardVersion scorecardVersion : scorecardVersions) {
            ScorecardVersionVo versionVo = new ScorecardVersionVo();
            BeanUtils.copyProperties(scorecardVersion, versionVo);
            scorecardVersionVoList.add(versionVo);
        }
        return scorecardVersionVoList;
    }


    @Override
    @Transactional
    public void addVersionList(List<ScorecardVersionVo> versionList) {
        for (ScorecardVersionVo versionVo : versionList) {
            if (Boolean.FALSE.equals(saveOrUpdateVersion(versionVo))) {
                throw new ApiException(ErrorCodeEnum.DECISION_SAVE_ERROR.getCode(),
                        ErrorCodeEnum.DECISION_SAVE_ERROR.getMessage() + ",版本号信息==》" + JSON.toJSONString(versionVo));
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveOrUpdateVersion(ScorecardVersionVo version) {
        ScorecardVersion scorecardVersion = BeanUtilsPlus.copyProperties(version, ScorecardVersion::new);
        if (Objects.isNull(scorecardVersion)) {
            return Boolean.TRUE;
        }
        if (Objects.isNull(scorecardVersion.getId())) {
            return addVersion(version);
        }
        return updateVersion(version);
    }

    @Override
    public Long checkAndAddVersion(ScorecardVersionVo version) {
        if (StringUtils.isEmpty(version.getScorecardCode())) {
            throw new ApiException(ErrorCodeEnum.DECISION_CODE_CAN_NOT_NULL);
        }
        version.setStatus(ComponentVersionStatusEnum.NEW.getStatus());
        List<ScorecardVersionVo> scorecardVersionVos =
                queryVersionByScorecardCodes(Collections.singletonList(version.getScorecardCode()), null);
        version.setOrganId(SessionManager.getLoginAccount().getOrganId());
        //如果是初始
        if (CollectionUtils.isEmpty(scorecardVersionVos)) {
            version.setId(null);
            version.setVersionNo(SysConstant.ZERO);
            //装配节点类型
            if (!CollectionUtils.isEmpty(version.getScorecardDimension())) {
                version.getScorecardDimension().forEach(ScorecardDimensionVo::recursionNodeType);
            }
        } else {
            ScorecardVersionVo newVersion = scorecardVersionVos.stream()
                    .filter(x -> Objects.equals(x.getStatus(), ComponentVersionStatusEnum.NEW.getStatus()))
                    .findFirst().orElse(null);
            //如果不存在新建，版本号为最大版本号+1
            if (Objects.isNull(newVersion)) {
                ScorecardVersionVo maxVersion = scorecardVersionVos.stream()
                        .max(Comparator.comparing(ScorecardVersionVo::getVersionNo)).orElse(null);
                if (Objects.isNull(maxVersion)) {
                    throw new ApiException(ErrorCodeEnum.ERROR_DECISION_VERSION);
                }
                version.setVersionNo(maxVersion.getVersionNo() + 1);
                version.setDescription("新建版本");
                //版本及详情id置空
                version.recurrenceSetIdIsNull();
            } else {
                //如果存在新建的，则覆盖版本的全部信息
                version.setId(newVersion.getId());
            }
        }

        Boolean execute = transactionTemplate.execute(status -> {
            try {
                //更新规则的更新人，更新时间
                Scorecard scorecard = new Scorecard();
                scorecard.setUpdatedTime(DateUtil.now());
                scorecard.setUpdateUserId(SessionManager.getLoginUserId());
                boolean update = scorecardService.update(scorecard,
                        new LambdaQueryWrapper<Scorecard>().eq(Scorecard::getCode, version.getScorecardCode()));
                return update && scorecardVersionService.saveOrUpdateVersion(version);
            } catch (Exception e) {
                status.setRollbackOnly();
                log.error("评分卡新建版本失败，版本==》{}", JSON.toJSONString(version), e);
                throw new ApiException(ErrorCodeEnum.DECISION_VERSION_NEW_ERROR);
            }
        });
        if (Boolean.FALSE.equals(execute)) {
            throw new ApiException(ErrorCodeEnum.DECISION_VERSION_NEW_ERROR);
        }
        return version.getId();
    }

    @Override
    public void lockScorecard(Long versionId) {
        ScorecardVersion scorecardVersion = this.getById(versionId);
        if (!Objects.equals(scorecardVersion.getStatus(), ComponentVersionStatusEnum.NEW.getStatus())) {
            throw new ApiException(ErrorCodeEnum.DECISION_LOCK_ERROR_001);
        }
        Scorecard scorecard = scorecardService.getOne(new LambdaQueryWrapper<Scorecard>()
                .eq(Scorecard::getCode, scorecardVersion.getScorecardCode()));
        if (Objects.isNull(scorecard)) {
            throw new ApiException(ErrorCodeEnum.PARAMS_EXCEPTION);
        }

        //校验当前版本信息完整性
        Set<String> emptyFieldSet = new HashSet<>();
        ScorecardVersionVo scorecardVersionVo = queryById(versionId);
        ComponentCommonContext.checkParamNotEmpty(scorecardVersionVo, emptyFieldSet);
        if (!CollectionUtils.isEmpty(emptyFieldSet)) {
            log.info(ErrorCodeEnum.INCOMPLETE_COMPONENT_INFORMATION.getMessage() + ",versionId:{},emptyFieldSet:{}",
                    versionId, JSON.toJSONString(emptyFieldSet));
            throw new ApiException(ErrorCodeEnum.INCOMPLETE_COMPONENT_INFORMATION);
        }

        scorecardVersionVo.getScorecardDimension().forEach(scorecardDimensionVo ->
                scorecardDimensionVo.getChildren().forEach(scorecardDetailVo -> {
                    if (!scorecardDetailVo.getCondition().matches("^(([\\[(])(\\d(\\d)*(\\.(\\d)+)?)|\\(),((\\d(\\d)*(\\.(\\d)+)?([])]))|\\))$")) {
                        throw new ApiException(ErrorCodeEnum.SERVER_ERROR.getCode(), "区间不正确:" + scorecardDetailVo.getCondition());
                    }
                }));
        scorecardVersion.setStatus(ComponentVersionStatusEnum.ENABLE.getStatus());
        transactionTemplate.execute(status -> {
            try {
                this.updateById(scorecardVersion);
                scorecard.setStatus(ComponentStatusEnum.ENABLE.getStatus());
                scorecardService.updateById(scorecard);
                return Boolean.TRUE;
            } catch (Exception e) {
                status.setRollbackOnly();
                log.error("评分卡锁定规则失败，版本id==>{}", versionId, e);
                throw new ApiException(ErrorCodeEnum.DECISION_LOCK_ERROR_002.getCode(), ErrorCodeEnum.DECISION_LOCK_ERROR_002.getMessage());
            }
        });
    }

    @Override
    public ResponseEntityDto<PageResult<List<ScorecardVersionListVo>, ScorecardVersion>> listByScorecardCode(AssemblyRuleCodeReq req) {
        PageMethod.startPage(req.getPageNo(), req.getPageSize());
        List<ScorecardVersion> list = this.list(new LambdaQueryWrapper<ScorecardVersion>()
                .eq(ScorecardVersion::getScorecardCode, req.getRuleCode()));
        List<ScorecardVersionListVo> scorecardVersionListVos =
                BeanUtilsPlus.copyElements(list, ScorecardVersionListVo::new);
        if (CollectionUtils.isEmpty(list)) {
            return PageResult.success(new ArrayList<>(), new PageInfo<>());
        }
        SSOUserInfoReqDto ssoUserInfoReqDto = new SSOUserInfoReqDto();
        Set<Long> userIds = new HashSet<>();
        scorecardVersionListVos.forEach(x -> {
            userIds.add(x.getCreateUserId());
            userIds.add(x.getUpdateUserId());
        });
        ssoUserInfoReqDto.setId(new ArrayList<>(userIds));
        Map<Long, String> sysMap = ssoService.getUserInfos(ssoUserInfoReqDto).stream()
                .collect(Collectors.toMap(SSOUserInfoRespDto::getId, SSOUserInfoRespDto::getName));
        scorecardVersionListVos.forEach(x ->
                x.setStatusDesc(Objects.requireNonNull(ComponentVersionStatusEnum.get(x.getStatus())).getName())
                        .setCreateUserName(sysMap.getOrDefault(x.getCreateUserId(), SysConstant.EMPTY_STRING))
                        .setUpdateUserName(sysMap.getOrDefault(x.getUpdateUserId(), SysConstant.EMPTY_STRING))
                        .setVersionNoDesc("V" + x.getVersionNo()));
        return PageResult.success(scorecardVersionListVos, new PageInfo<>(list));
    }

    @Override
    @Transactional
    public boolean addVersion(ScorecardVersionVo versionVo) {
        return versionMapper.insert(versionVo) > 0
                && addVersionDetail(versionVo)
                && outputService.insertTacticsOutput(versionVo.getId(), versionVo.getStrategyOutputList());
    }

    @Transactional
    public boolean addVersionDetail(ScorecardVersionVo version) {
        List<ScorecardDimensionVo> DimensionVos = version.getScorecardDimension();
        for (ScorecardDimensionVo dimensionVo : DimensionVos) {
            ScorecardDimension dimension = new ScorecardDimension();
            BeanUtils.copyProperties(dimensionVo, dimension);
            dimension.setVersionId(version.getId());
            // 数据库 insertOne(dimension)  之后dimension就有id了 (把id传给子表)
            boolean saveDimension = scorecardDimensionService.save(dimension);
            if (!saveDimension) {
                throw new ApiException(ErrorCodeEnum.SERVER_ERROR.getCode(), ErrorCodeEnum.SERVER_ERROR.getMessage());
            }
            List<ScorecardDetailVo> detailVos = dimensionVo.getChildren();  // 明细Array

            // 递归 detailVos
            recursionOfAdd(detailVos, dimension.getId(), 0);
        }
        return true;
    }

    @Override
    @Transactional
    public boolean copyVersion(ScorecardVersionVo version) {
        ScorecardVersionVo versionVo = this.queryById(version.getId());
        versionVo.setId(null);
        versionVo.setDescription(version.getDescription());
        return this.addVersion(versionVo);
    }

    @Override
    @Transactional
    public boolean updateVersion(ScorecardVersionVo version) {
        int count = versionMapper.updateById(version);
        this.cleanScorecardVersion(version);
        return count > 0
                && this.addVersionDetail(version)
                && outputService.updateTacticsOutput(version.getId(), version.getStrategyOutputList(), ComponentTypeEnum.SCORECARD.getType());
    }

    @Override
    @Transactional
    public boolean updateStatus(StatusParam statusParam) {
//        int result = versionMapper.updateStatus(ids, status);
        LambdaQueryWrapper<ScorecardVersion> updateWrapper = new LambdaQueryWrapper<>();
        updateWrapper.in(ScorecardVersion::getId, statusParam.getIds());
        updateWrapper.eq(ScorecardVersion::getScorecardCode, statusParam.getStrategyId());
        ScorecardVersion scorecardVersion = new ScorecardVersion();
        scorecardVersion.setStatus(statusParam.getStatus());
        boolean update = this.update(scorecardVersion, updateWrapper);
        return update;
    }

//    /**
//     * 组装评分卡维度信息
//     * @param scorecardDimension
//     * @return
//     */
//    private ScorecardDimensionVo assemblyScorecardDimensionVo(ScorecardDimension scorecardDimension) {
//        ScorecardDimensionVo scorecardDimensionVo = new ScorecardDimensionVo();
//        BeanUtils.copyProperties(scorecardDimension, scorecardDimensionVo);
//        List<ScorecardDetailVo> children = new ArrayList<>();
//        LambdaQueryWrapper<ScorecardDetail> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(ScorecardDetail::getDimensionId, scorecardDimension.getId());
//        List<ScorecardDetail> scorecardDetails = scorecardDetailService.list(queryWrapper);
//
//        List<ScorecardDetail> scorecardDetailsGroup = scorecardDetails.stream().filter(item -> item.getParentId().intValue() == 0).collect(Collectors.toList());
//        for (ScorecardDetail scorecardDetail : scorecardDetailsGroup) {
//            ScorecardDetailVo scorecardDetailVo = assemblyScorecardDetailVo(scorecardDetail, scorecardDetails);
//            children.add(scorecardDetailVo);
//        }
//        scorecardDimensionVo.setChildren(children);
//        return scorecardDimensionVo;
//    }

    /**
     * 组装评分卡维度信息
     *
     * @param scorecardDimension
     * @return
     */
    private ScorecardDimensionVo assemblyScorecardDimensionVo(ScorecardDimension scorecardDimension) {
        ScorecardDimensionVo scorecardDimensionVo = new ScorecardDimensionVo();
        BeanUtils.copyProperties(scorecardDimension, scorecardDimensionVo);
        List<ScorecardDetailVo> children = new ArrayList<>();

        List<ScorecardDetail> scorecardDetails = scorecardDetailService.getDetailListByDimensionId(scorecardDimension.getId());
        List<ScorecardDetail> scorecardDetailsGroup = scorecardDetails.stream()
                .filter(item -> item.getParentId().intValue() == 0).collect(Collectors.toList());
        for (ScorecardDetail scorecardDetail : scorecardDetailsGroup) {
            ScorecardDetailVo scorecardDetailVo = assemblyScorecardDetailVo(scorecardDetail, scorecardDetails);
            children.add(scorecardDetailVo);
        }
        scorecardDimensionVo.setChildren(children);
        return scorecardDimensionVo;
    }

    /**
     * 递归组装评分卡明细信息
     *
     * @param scorecardDetail
     * @param scorecardDetails
     * @return
     */
    private ScorecardDetailVo assemblyScorecardDetailVo(ScorecardDetail scorecardDetail, List<ScorecardDetail> scorecardDetails) {
        ScorecardDetailVo scorecardDetailVo = new ScorecardDetailVo();
        BeanUtils.copyProperties(scorecardDetail, scorecardDetailVo);
        scorecardDetailVo.setCondition(assemblyCondition(scorecardDetail.getId()));
        List<ScorecardDetailVo> children = new ArrayList<>();
        List<ScorecardDetail> detailList = scorecardDetails.stream().filter(item -> item.getParentId().equals(scorecardDetail.getId())).collect(Collectors.toList());
        for (ScorecardDetail cardDetail : detailList) {
            ScorecardDetailVo cardDetailVo = this.assemblyScorecardDetailVo(cardDetail, scorecardDetails);
            children.add(cardDetailVo);
        }
        scorecardDetailVo.setChildren(children);


        List<Field> fields = fieldService.queryByEns(Arrays.asList(scorecardDetail.getFieldCode()));


        if (null != fields && fields.size() > 0) {
            scorecardDetailVo.setFieldName(fields.get(0).getFieldName());
        }

        return scorecardDetailVo;
    }

//    /**
//     * 组装区间信息
//     *
//     * @param detailId
//     * @return
//     */
//    private String assemblyCondition(Integer detailId) {
//        String[] conditionArr = new String[]{"(", ")"};
//
//        LambdaQueryWrapper<ScorecardDetailCondition> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(ScorecardDetailCondition::getDetailId, detailId);
//        List<ScorecardDetailCondition> scorecardDetailConditions = scorecardDetailConditionService.list(queryWrapper);
//        if (scorecardDetailConditions != null && !scorecardDetailConditions.isEmpty()) {
//            for (ScorecardDetailCondition detailCondition : scorecardDetailConditions) {
//                String operator = detailCondition.getOperator();
//                if (EngineOperator.OPERATOR_GREATER_RELATION.equals(operator)
//                        || EngineOperator.OPERATOR_GREATER_EQUALS_RELATION.equals(operator)) {
//                    conditionArr[0] = convertOperatorToBrackets(operator) + detailCondition.getFieldValue();
//                } else if (EngineOperator.OPERATOR_LESS_RELATION.equals(operator)
//                        || EngineOperator.OPERATOR_LESS_EQUALS_RELATION.equals(operator)) {
//                    conditionArr[1] = detailCondition.getFieldValue() + convertOperatorToBrackets(operator);
//                }
//            }
//        }
//        String condition = StringUtils.join(conditionArr, CommonConst.SYMBOL_COMMA);
//        return condition;
//    }

    /**
     * 组装区间信息
     *
     * @param detailId
     * @return
     */
    private String assemblyCondition(Integer detailId) {
        String[] conditionArr = new String[]{"(", ")"};
        List<ScorecardDetailCondition> scorecardDetailConditions = scorecardDetailConditionService.getConditionListByDetailId(detailId);
        if (scorecardDetailConditions != null && !scorecardDetailConditions.isEmpty()) {
            for (ScorecardDetailCondition detailCondition : scorecardDetailConditions) {
                String operator = detailCondition.getOperator();
                if (EngineOperator.OPERATOR_GREATER_RELATION.equals(operator)
                        || EngineOperator.OPERATOR_GREATER_EQUALS_RELATION.equals(operator)) {
                    conditionArr[0] = convertOperatorToBrackets(operator) + detailCondition.getFieldValue();
                } else if (EngineOperator.OPERATOR_LESS_RELATION.equals(operator)
                        || EngineOperator.OPERATOR_LESS_EQUALS_RELATION.equals(operator)) {
                    conditionArr[1] = detailCondition.getFieldValue() + convertOperatorToBrackets(operator);
                }
            }
        }
        String condition = StringUtils.join(conditionArr, CommonConst.SYMBOL_COMMA);
        return condition;
    }

    /**
     * 运算符转换为括号
     *
     * @param operator
     * @return
     */
    private String convertOperatorToBrackets(String operator) {
        String brackets = "";
        switch (operator) {
            case EngineOperator.OPERATOR_GREATER_RELATION:
                brackets = EngineOperator.OPERATOR_LEFT_PARENTHESES;
                break;
            case EngineOperator.OPERATOR_GREATER_EQUALS_RELATION:
                brackets = EngineOperator.OPERATOR_LEFT_BRACKET;
                break;
            case EngineOperator.OPERATOR_LESS_RELATION:
                brackets = EngineOperator.OPERATOR_RIGHT_PARENTHESES;
                break;
            case EngineOperator.OPERATOR_LESS_EQUALS_RELATION:
                brackets = EngineOperator.OPERATOR_RIGHT_BRACKET;
                break;
            default:
                break;
        }
        return brackets;
    }

    /**
     * 清除评分卡版本信息
     *
     * @param versionVo
     */
    private void cleanScorecardVersion(ScorecardVersionVo versionVo) {
        // 删除评分卡主表
        // removeById(scorecardVo.getId());

        // 删除维度信息
        LambdaQueryWrapper<ScorecardDimension> dimensionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dimensionLambdaQueryWrapper.eq(ScorecardDimension::getVersionId, versionVo.getId());
        List<ScorecardDimension> scorecardDimensions = scorecardDimensionService.list(dimensionLambdaQueryWrapper);
        if (scorecardDimensions == null || scorecardDimensions.isEmpty()) {
            return;
        }
        List<Integer> dimensionIds = scorecardDimensions.stream().map(item -> item.getId()).collect(Collectors.toList());
        scorecardDimensionService.removeByIds(dimensionIds);
        //删除输出字段
        // 删除维度明细信息
        LambdaQueryWrapper<ScorecardDetail> detailLambdaQueryWrapper = new LambdaQueryWrapper<>();
        detailLambdaQueryWrapper.in(ScorecardDetail::getDimensionId, dimensionIds);
        List<ScorecardDetail> scorecardDetails = scorecardDetailService.list(detailLambdaQueryWrapper);
        if (scorecardDetails == null || scorecardDetails.isEmpty()) {
            return;
        }
        List<Integer> detailIds = scorecardDetails.stream().map(item -> item.getId()).collect(Collectors.toList());
        scorecardDetailService.removeByIds(detailIds);

        // 删除维度明细条件信息
        LambdaQueryWrapper<ScorecardDetailCondition> conditionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        conditionLambdaQueryWrapper.in(ScorecardDetailCondition::getDetailId, detailIds);
        scorecardDetailConditionService.remove(conditionLambdaQueryWrapper);
    }

    @Override
    public List<String> queryFieldEnByVersionId(Long versionId) {
        Set<String> fieldEns = new HashSet<>();
        LambdaQueryWrapper<ScorecardDimension> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ScorecardDimension::getVersionId, versionId);
        queryWrapper.select(ScorecardDimension::getId);
        List<ScorecardDimension> dimensionList = scorecardDimensionService.list(queryWrapper);
        Set<Integer> dimensionIds = new HashSet<>();
        if (dimensionList != null && dimensionList.size() > 0) {
            for (ScorecardDimension scorecardDimension : dimensionList) {
                dimensionIds.add(scorecardDimension.getId());
            }
        }
        if (dimensionIds.size() > 0) {
            LambdaQueryWrapper<ScorecardDetail> detailWrapper = new LambdaQueryWrapper<>();
            detailWrapper.in(ScorecardDetail::getDimensionId, dimensionIds);
            List<ScorecardDetail> list = scorecardDetailService.list(detailWrapper);
            if (list != null && list.size() > 0) {
                for (ScorecardDetail detail : list) {
                    String fieldCode = detail.getFieldCode();
                    fieldEns.add(fieldCode);
                    String custom = detail.getCustom();
                    fieldEns.addAll(CustomValueUtils.getFieldEnSet(custom));
                }
            }
        }
        return new ArrayList<>(fieldEns);
    }

    private void recursionOfAdd(List<ScorecardDetailVo> detailVos, Integer dimensionId, Integer parentId) {

        if (detailVos == null || detailVos.size() < 1) {
            return;
        }

        for (ScorecardDetailVo detailVo : detailVos) {
            ScorecardDetail detail = new ScorecardDetail();
            BeanUtils.copyProperties(detailVo, detail);
            detail.setDimensionId(dimensionId);  // 设置 明细表 的 维度id
            detail.setParentId(parentId);

            String conditionStr = detailVo.getCondition().replace(" ", "");  // 去掉空格
            if (StringUtils.isNotEmpty(conditionStr)) {
                if (!conditionStr.matches("^((\\[|\\()(\\d(\\d)*(\\.(\\d)+)?)|\\(),((\\d(\\d)*(\\.(\\d)+)?(\\]|\\)))|\\))$")) {
                    throw new ApiException(ErrorCodeEnum.SERVER_ERROR.getCode(), "区间不正确:" + conditionStr);
                }
                String[] split = conditionStr.split(",");
                if (split[0].length() > 1 && split[1].length() > 1) {
                    detail.setLogicalSymbol("&&");
                } else if (split[0].length() <= 1 && split[1].length() <= 1) {
                    log.error("区间有误，conditionStr:{}", conditionStr);
                } else {
                    detail.setLogicalSymbol(null);
                }
            }

            // 叶子节点和非叶子节点 情况处理
            if (detailVo.getChildren() == null || detailVo.getChildren().size() < 1) {
                // 叶子节点
                detail.setNodeType(1);
            } else {
                // 非叶子节点
                detail.setNodeType(0);
                detail.setScore(null);
            }

            // 数据库 insertOne(detail)  之后detail就有id了 (把id传给子表)
            boolean saveDetail = scorecardDetailService.save(detail);
            if (!saveDetail) {
                throw new ApiException(ErrorCodeEnum.SERVER_ERROR.getCode(), ErrorCodeEnum.SERVER_ERROR.getMessage());
            }
            if (StringUtils.isNotEmpty(conditionStr)) {
                // 处理并添加 Condition
                this.addCondition(conditionStr, detail.getId());
            }

            this.recursionOfAdd(detailVo.getChildren(), dimensionId, detail.getId());  // 递归 树
        }

    }

    /**
     * 处理并添加 Condition
     *
     * @param conditionStr Condition字符串
     * @param detailId     明细id
     */
    private void addCondition(String conditionStr, Integer detailId) {

        List<ScorecardDetailCondition> conditionList = new ArrayList<>();  // Condition 数组
        if (!conditionStr.matches("^((\\[|\\()(\\d(\\d)*(\\.(\\d)+)?)|\\(),((\\d(\\d)*(\\.(\\d)+)?(\\]|\\)))|\\))$")) {
            throw new ApiException(ErrorCodeEnum.SERVER_ERROR.getCode(), "区间不正确:" + conditionStr);
        }
        //修正评分卡逻辑
        String[] strings = conditionStr.split(",");
        String left = strings[0];
        String right = strings[1];
        //处理左半边
        if (StringUtils.isNotBlank(left)) {
            ScorecardDetailCondition condition = new ScorecardDetailCondition();
            condition.setDetailId(detailId);
            if (left.startsWith("(")) {
                condition.setOperator(">");
            } else if (left.startsWith("[")) {
                condition.setOperator(">=");
            }
            if (left.length() > 1) {
                condition.setFieldValue(left.substring(1));
                conditionList.add(condition);
            }


        }
        //处理右半边
        if (StringUtils.isNotBlank(right)) {
            ScorecardDetailCondition condition = new ScorecardDetailCondition();
            condition.setDetailId(detailId);
            if (right.endsWith(")")) {
                condition.setOperator("<");
            } else if (right.endsWith("]")) {
                condition.setOperator("<=");
            }
            if (right.length() > 1) {
                condition.setFieldValue(right.substring(0, right.length() - 1));
                conditionList.add(condition);
            }
        }

        if (conditionList.size() > 0) {
            boolean saveCondition = scorecardDetailConditionService.saveBatch(conditionList);
            if (!saveCondition) {
                throw new ApiException(ErrorCodeEnum.SERVER_ERROR.getCode(), ErrorCodeEnum.SERVER_ERROR.getMessage());
            }
        }

    }


}
